/*
 * Created on Feb 7, 2005
 * Created by dfhuynh
 */
package edu.mit.simile.longwell.schema.impl;

import java.io.File;
import java.text.DateFormat;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Vector;

import org.apache.derby.tools.sysinfo;
import org.apache.log4j.Logger;
import org.apache.tomcat.jni.Directory;

import com.hp.hpl.jena.rdf.model.AnonId;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.NodeIterator;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.ResIterator;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.rdf.model.impl.PropertyImpl;
import com.hp.hpl.jena.vocabulary.DC;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;

import edu.mit.simile.SimileUtilities;
import edu.mit.simile.longwell.Cache;
import edu.mit.simile.longwell.Profile;
import edu.mit.simile.longwell.StructuredModelBase;
import edu.mit.simile.longwell.jfresnel.FresnelDoc;
import edu.mit.simile.longwell.schema.ISchemaModel;
import edu.mit.simile.longwell.schema.IStructuredClass;
import edu.mit.simile.longwell.schema.IStructuredProperty;
import edu.mit.simile.longwell.schema.IStructuredSchema;
import fr.inria.jfresnel.Format;
import fr.inria.jfresnel.FresnelDocument;
import fr.inria.jfresnel.FresnelParser;
import fr.inria.jfresnel.Lens;
import fr.inria.jfresnel.PropertyVisibility;
import fr.inria.jfresnel.fsl.FSLHierarchyStore;
import fr.inria.jfresnel.fsl.FSLNSResolver;
import fr.inria.jfresnel.fsl.jena.FSLJenaEvaluator;
import fr.inria.jfresnel.fsl.jena.FSLJenaHierarchyStore;
import fr.inria.jfresnel.jena.FresnelJenaParser;
import fr.inria.jfresnel.jena.JenaLens;
import fr.inria.jfresnel.Constants;
/**
 * @author dfhuynh
 */
public class LocalSchemaModel extends StructuredModelBase implements ISchemaModel {
	final static private String s_pseudoURIPrefix = "urn:edu.mit.simile.longwell:anonymous#";
	
	final static private Logger s_logger = Logger.getLogger(LocalSchemaModel.class);
	
	protected SchemaRegistry 	m_schemaRegistry;
	protected Map				m_typeLabelPropertyCache = new HashMap();
	protected Cache				m_objectToLabel = new Cache(1000, LocalSchemaModel.class, "object-to-label");
	protected Cache				m_objectToAbbreviatedLabel = new Cache(1000, LocalSchemaModel.class, "object-to-abbreviated-label");
	protected Cache				m_objectToType = new Cache(1000, LocalSchemaModel.class, "object-to-type");
	protected Cache				m_objectsToProperties = new Cache(10, LocalSchemaModel.class, "objects-to-properties");
	protected Set				m_allObjects;
	private FresnelDoc fresnelDoc;
	
	public LocalSchemaModel(Profile profile, File dir) {
		super(profile, dir);
//		if(dir.exists()){
//			dir.delete();
//		}
		if (!dir.exists()) {
			dir.mkdir();
		}
		
		m_schemaRegistry = new SchemaRegistry(
			m_profile, new File(dir,"schema-registry"));
	}
	
	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.model.ISchemaModel#getAllObjects()
	 */
	public Set getAllObjects() {
		if (m_allObjects == null) {
			m_allObjects = new HashSet();
			
			Iterator i = getStructuredSchemas().iterator();
			while (i.hasNext()) {
				IStructuredSchema sSchema = (IStructuredSchema) i.next();
				
				m_allObjects.addAll(sSchema.getObjects());
			}
		}
		return m_allObjects;
	}
	
	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.model.ISchemaModel#getStructuredSchemas()
	 */
	public Set getStructuredSchemas() {
		return m_schemaRegistry.getStructuredSchemas();
	}

	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.model.ISchemaModel#guessSchemasOfResource(com.hp.hpl.jena.rdf.model.Resource)
	 */
	public Set guessSchemasOfResource(Resource resource) {
		return m_schemaRegistry.guessSchemasOfResource(resource);
	}
	
	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.model.ISchemaModel#getClassesOfResources(java.util.Set)
	 */
	public Set getClassesOfResources(Set resources) {
		Set sSchemas = m_schemaRegistry.getStructuredSchemas();
		Iterator i = sSchemas.iterator();
		while (i.hasNext()) {
			
			StructuredSchema sSchema = (StructuredSchema) i.next();
			Set sClasses = sSchema.getClasses();
			Set objects = sSchema.getObjects();
			if (objects.hashCode() == resources.hashCode()) {
				return sClasses;
			}				


			
			Iterator j = sClasses.iterator();
			while (j.hasNext()) {
				StructuredClass sClass = (StructuredClass) j.next();
				objects = sClass.getObjects();
				
				if (objects.hashCode() == resources.hashCode()) {
					Set classes = new HashSet();
					
					classes.add(sClass);
					
					return classes;
				}
			}
		}
		
		Set classes = new HashSet();
		i = resources.iterator();
		while (i.hasNext()) {
			IStructuredClass sClass = objectToStructuredClass((Resource) i.next());
			if (sClass != null) {
				classes.add(sClass);
			}						
		}
		return classes;
	}
	
	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.schema.ISchemaModel#getSortedStructuredProperties(java.util.Set)
	 */
	public SortedSet getSortedStructuredProperties(Set objects) {
		SortedSet sProperties = (SortedSet) m_objectsToProperties.get(objects);
		if (sProperties == null) {
			ISchemaModel schemaModel = m_profile.getSchemaModel();
			Set 		 sClasses = schemaModel.getClassesOfResources(objects);
			
			sProperties = new TreeSet(new Comparator() {
				public boolean equals(Object obj) {
					return false;
				}
	
				public int compare(Object o1, Object o2) {
					IStructuredProperty p1 = (IStructuredProperty) o1;
					IStructuredProperty p2 = (IStructuredProperty) o2;
					
					long f1 = p1.countOccurrences();
					long f2 = p2.countOccurrences();
					int i = f1 == f2 ? 0 : (f1 > f2 ? -1 : 1);
					if (i == 0) {
						i = p1.getURI().compareTo(p2.getURI());
					}
					return i;
				}
			});
			
			Iterator i = sClasses.iterator();
			while (i.hasNext()) {
				
				IStructuredClass sClass = (IStructuredClass) i.next();
				
				if (sClass.countObjects() > 0) {
					sProperties.addAll(sClass.getProperties(objects));
				}
			}
			
			m_objectsToProperties.put(objects, sProperties);
		}			
		return sProperties;
	}


	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.model.ISchemaModel#getStructuredSchema(java.lang.String)
	 */
	public IStructuredSchema getStructuredSchema(String uri) {
		return m_schemaRegistry.getStructuredSchema(uri);
	}
	
	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.model.ISchemaModel#getStructuredClass(com.hp.hpl.jena.rdf.model.Resource)
	 */
	public IStructuredClass getStructuredClass(Resource resource) {
		return m_schemaRegistry.getStructuredClass(resource);
	}
	
	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.model.ISchemaModel#getStructuredProperty(com.hp.hpl.jena.rdf.model.Property)
	 */
	public IStructuredProperty getStructuredProperty(Property property) {
		return m_schemaRegistry.getStructuredProperty(property);
	}
	
	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.model.core.ISchemaModel#resourceToPseudoURI(com.hp.hpl.jena.rdf.model.Resource)
	 */
	synchronized public String resourceToPseudoURI(Resource r) {
		String uri = r.getURI();
		if (uri == null) {
			uri = s_pseudoURIPrefix + r.getId();
		}
		return uri;
	}

	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.model.core.ISchemaModel#pseudoURIToResource(java.lang.String)
	 */
	synchronized public Resource pseudoURIToResource(String pseudoURI) {
		Model model = getModel();
		
		if (pseudoURI.startsWith(s_pseudoURIPrefix)) {
			return model.createResource(
				new AnonId(pseudoURI.substring(s_pseudoURIPrefix.length())));
		} else {
			return model.createResource(pseudoURI);
		}
	}

	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.model.core.ISchemaModel#getLabel(com.hp.hpl.jena.rdf.model.Resource, com.hp.hpl.jena.rdf.model.Model, java.lang.String, boolean)
	 */
	
	synchronized public String getImage(Resource r){
		Model schemaModel = getModel();
		String image="";
		/*
		 * Find label based on explicit types on the object
		 */
		IStructuredClass sClass = objectToStructuredClass(r);
		if (sClass != null) {
			String typeURI = sClass.getURI();
			if(typeURI.contains("Person")){
				image="person.png";
			}
			else if(typeURI.contains("Fabbricato")){
				image="home.png";
			}
			else if(typeURI.contains("Versamento")){
				image="coins.png";
			}		
			else if(typeURI.contains("Contributo")){
				image="payment.png";
			}	
			else if(typeURI.contains("Elettrica")){
				image="electric.png";
			}	
			else if(typeURI.contains("Famiglia")){
				image="family.png";
			}	
			else if(typeURI.contains("Indirizzo")){
				image="address.png";
			}			
		}
		return image;
	}
	
	synchronized public String getLabel(Resource r, String locale, boolean abbreviate) {
		String label = (String) (abbreviate ? 
				m_objectToAbbreviatedLabel.get(r) : 
				m_objectToLabel.get(r));
		
		if (label == null) {
			if (r instanceof Property) {
				IStructuredProperty sProperty =
					getStructuredProperty((Property) r);
				
				if (sProperty != null) {
					label = sProperty.getLabel(locale);
				}
			}
			
			if (label == null) {
				Model myModel = getModel();
				
				if (myModel.contains(r, RDF.type, RDF.Property)) {
					label = getStructuredProperty(myModel.createProperty(r.getURI())).getLabel(locale);
				} else {
					label = getObjectLabel(r, m_profile.getModel(), abbreviate);
				}
			}
			if (label == null) {
				label = "";
			}
		
			if (abbreviate) {
				m_objectToAbbreviatedLabel.put(r, label);
			} else {
				m_objectToLabel.put(r, label);
			}
		}
		return label;
	}

	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.model.core.ISchemaModel#getYoungestTypes(com.hp.hpl.jena.rdf.model.Resource, com.hp.hpl.jena.rdf.model.Model)
	 */
	synchronized public Set getYoungestTypes(Resource r, Model model) {
		Set types = new HashSet();
		
		NodeIterator ni = model.listObjectsOfProperty(r, RDF.type);
		while (ni.hasNext()) {
			RDFNode node = ni.nextNode();
			if (node instanceof Resource) {
				types.add(node);
			}
		}
		
		Set supertypes = new HashSet();
		Iterator i = types.iterator();
		while (i.hasNext()) {
			Resource r2 = (Resource) i.next();
			
			ni = getModel().listObjectsOfProperty(r, RDFS.subClassOf);
			while (ni.hasNext()) {
				supertypes.add(ni.nextNode());
			}
		}
		
		types.removeAll(supertypes);
		
		return types;
	}
	
	public SortedSet getPropertyValuePairsOriginal(Resource r, String locale, boolean forward) {
		
		Model model = m_profile.getModel();
		
		TreeSet pairs = new TreeSet(new PropertyValuePairComparator());
		
		if (forward) {
			Set properties = new HashSet();
			
			StmtIterator si = model.listStatements(r, null, (RDFNode) null);

			while (si.hasNext()) {
				//properties for each item
				properties.add(si.nextStatement().getPredicate());
			}
			
			
			Iterator i = properties.iterator();
			while (i.hasNext()) {
				Property p = (Property) i.next();
				IStructuredProperty sProperty = m_schemaRegistry.getStructuredProperty(p);
				
				boolean isLiteral = sProperty == null ? false :
					 (sProperty.getTypeConfidence(
					 	IStructuredProperty.s_type_literal) > 0.5);
				boolean isDate = sProperty == null ? false :
					(sProperty.getTypeConfidence(
						IStructuredProperty.s_type_dateTime) > 0.5);
				
				TreeSet values = new TreeSet(new LabeledObjectComparator());
				
				NodeIterator ni = model.listObjectsOfProperty(r, p);
				while (ni.hasNext()) {
					RDFNode node = ni.nextNode();
					if (node instanceof Resource) {
						values.add(makeLabeledResource((Resource) node, locale));
					} else {
						values.add(makeLabeledLiteral((Literal) node, locale, isDate));
					}
				}
				
				pairs.add(new PropertyValuePair(makeLabeledResource(p, locale), values, isLiteral));
			}
		} else {
			Set predicates = new HashSet();
			
			StmtIterator si = model.listStatements(null, null, r);
			while (si.hasNext()) {
				predicates.add(si.nextStatement().getPredicate());
			}
			
			Iterator i = predicates.iterator();
			while (i.hasNext()) {
				Property p = (Property) i.next();
				
				TreeSet referers = new TreeSet(new LabeledObjectComparator());
				
				ResIterator ri = model.listSubjectsWithProperty(p, r);
				while (ri.hasNext()) {
					Resource referer = ri.nextResource();
					referers.add(makeLabeledResource(referer, locale));
				}
				
				pairs.add(new PropertyValuePair(
					makeLabeledResource(p, locale), referers, false));
			}
		}
		return pairs;
		//return filterPairs(r, pairs,locale);
	}	
	
	
		/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.model.ISchemaModel#getPropertyValuePairs(com.hp.hpl.jena.rdf.model.Resource, java.lang.String, boolean)
	 */
	public SortedSet getPropertyValuePairs(Resource r, String locale, boolean forward) {
		
		Model model = m_profile.getModel();
		
		TreeSet pairs = new TreeSet(new PropertyValuePairComparator());
		
		if (forward) {
			Set properties = new HashSet();
			
			StmtIterator si = model.listStatements(r, null, (RDFNode) null);

			while (si.hasNext()) {
				//properties for each item
				properties.add(si.nextStatement().getPredicate());
			}
			
			
			Iterator i = properties.iterator();
			while (i.hasNext()) {
				Property p = (Property) i.next();
				IStructuredProperty sProperty = m_schemaRegistry.getStructuredProperty(p);
				
				boolean isLiteral = sProperty == null ? false :
					 (sProperty.getTypeConfidence(
					 	IStructuredProperty.s_type_literal) > 0.5);
				boolean isDate = sProperty == null ? false :
					(sProperty.getTypeConfidence(
						IStructuredProperty.s_type_dateTime) > 0.5);
				
				TreeSet values = new TreeSet(new LabeledObjectComparator());
				
				NodeIterator ni = model.listObjectsOfProperty(r, p);
				while (ni.hasNext()) {
					RDFNode node = ni.nextNode();
					if (node instanceof Resource) {
						values.add(makeLabeledResource((Resource) node, locale));
					} else {
						values.add(makeLabeledLiteral((Literal) node, locale, isDate));
					}
				}
				
				pairs.add(new PropertyValuePair(makeLabeledResource(p, locale), values, isLiteral));
			}
		} else {
			Set predicates = new HashSet();
			
			StmtIterator si = model.listStatements(null, null, r);
			while (si.hasNext()) {
				predicates.add(si.nextStatement().getPredicate());
			}
			
			Iterator i = predicates.iterator();
			while (i.hasNext()) {
				Property p = (Property) i.next();
				
				TreeSet referers = new TreeSet(new LabeledObjectComparator());
				
				ResIterator ri = model.listSubjectsWithProperty(p, r);
				while (ri.hasNext()) {
					Resource referer = ri.nextResource();
					referers.add(makeLabeledResource(referer, locale));
				}
				
				pairs.add(new PropertyValuePair(
					makeLabeledResource(p, locale), referers, false));
			}
		}
		//return pairs;
		if(pairs!=null && pairs.size()>0)
			return filterPairs(r, pairs,locale);
		else return pairs;
	}
	private FresnelDocument getFresnelDoc() throws Exception{
		if( fresnelDoc==null){
			Model model = m_profile.getModel();
			fresnelDoc = new FresnelDoc(model);
			FSLJenaEvaluator fje = fresnelDoc.getFresnelEvaluator();
			FresnelDocument fd=null;
			
			try {
				fd = fresnelDoc.getFresnelDocument();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return fd;
		}
		else 
			return fresnelDoc.getFresnelDocument();
	}
	private TreeSet filterPairs(Resource r, TreeSet pairs,String locale){
		TreeSet pairsFiltered = new TreeSet(new PropertyValuePairComparator());
		Model model = m_profile.getModel();
		
//		JenaLens lens = (JenaLens) fd.getLens("file:///home/nicola/#personLens");
//		String [] domains = lens.getBasicClassDomains();
//		for(int i = 0; i < domains.length; i++){
//			String domain = domains[i];
//			s_logger.info("Lens Domain: "+domain);
//		}
		
		String typep = r.getProperty(RDF.type).getObject().toString();
		s_logger.info("Reesource type: " + typep);
		
		
		Set properties= new HashSet();	
		
		
		FresnelDocument fd=null;
		try {
			fd = getFresnelDoc();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Lens[] lenses = fd.getLenses();
		
		for(int i=0;i<lenses.length;i++){
			JenaLens ln = (JenaLens) lenses[i];
			String lensClassDomain = ln.getBasicClassDomains()[0];
		
			if((lensClassDomain).equals(typep)){
				Vector<Statement> stmtVector = ln.getPropertyValuesToDisplay(r, fresnelDoc.getFresnelEvaluator(), null);	
				s_logger.info("Found " + stmtVector.size() + " properties to display for resource of type " + typep);
				for(int k = 0; k < stmtVector.size(); k++){
					Statement stmt = stmtVector.get(k);
					Property prop = stmt.getPredicate();
					properties.add(prop);
					s_logger.info("Property to display: " + prop.toString());
				}			
			}
		}
		
		if(properties.isEmpty()){
			StmtIterator si = model.listStatements(r, null, (RDFNode) null);
			while (si.hasNext()) {
				//properties for each item
				properties.add(si.nextStatement().getPredicate());
			}
		}
		
		Iterator i = properties.iterator();
		while (i.hasNext()) {
			Property p = (Property) i.next();
			IStructuredProperty sProperty = m_schemaRegistry.getStructuredProperty(p);
			
			boolean isLiteral = sProperty == null ? false :
				 (sProperty.getTypeConfidence(
				 	IStructuredProperty.s_type_literal) > 0.5);
			boolean isDate = sProperty == null ? false :
				(sProperty.getTypeConfidence(
					IStructuredProperty.s_type_dateTime) > 0.5);
			
			TreeSet values = new TreeSet(new LabeledObjectComparator());
			
			NodeIterator ni = model.listObjectsOfProperty(r, p);
			while (ni.hasNext()) {
				RDFNode node = ni.nextNode();
				if (node instanceof Resource) {
					values.add(makeLabeledResource((Resource) node, locale));
				} else {
					values.add(makeLabeledLiteral((Literal) node, locale, isDate));
				}
			}
			
			pairsFiltered.add(new PropertyValuePair(makeLabeledResource(p, locale), values, isLiteral));
		}


		
//		Iterator<PropertyValuePair> ipairs = pairs.iterator();
//		TreeSet pairsFilered = new TreeSet(new PropertyValuePairComparator());
//		
//		while(ipairs.hasNext()){
//			PropertyValuePair pair = ipairs.next();
//			LabeledObject property = pair.getProperty();
//			SortedSet values = pair.getValues();
//		}
		
		return pairsFiltered;
	}
	
	protected LabeledObject makeLabeledResource(Resource r, String locale) {
		
		return new LabeledObject(r, getLabel(r, locale, false));
	}
	
	protected LabeledObject makeLabeledLiteral(Literal l, String locale, boolean isDate) {
		String s = l.getString();
		if (isDate) {
			try {
				s = DateFormat.getDateTimeInstance()
					.format(SimileUtilities.parseDate(s));
				if(s.length()>11)
					s=s.substring(0, 11);
			} catch (Exception e) {
			}
		}
		return new LabeledObject(l, s);
	}

	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.model.IStructuredModel#dispose()
	 */
	synchronized public void dispose() {
		m_schemaRegistry.dispose();
		m_schemaRegistry = null;
		flushCaches();
		super.dispose();
	}

	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.model.IStructuredModel#onAfterAdd(com.hp.hpl.jena.rdf.model.Model)
	 */
	synchronized public void onAfterAdd(Model model) {
		super.onAfterAdd(model);
		m_schemaRegistry.onAfterAdd(model);
		flushCaches();
	}

	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.model.IStructuredModel#onAfterRemove(com.hp.hpl.jena.rdf.model.Model)
	 */
	synchronized public void onAfterRemove(Model model) {
		super.onAfterRemove(model);
		m_schemaRegistry.onAfterRemove(model);
		flushCaches();
	}
	
	protected void flushCaches() {
		m_typeLabelPropertyCache.clear();
		m_objectToLabel.clear();
		m_objectToAbbreviatedLabel.clear();
		m_objectToType.clear();
		m_objectsToProperties.clear();
		m_allObjects = null;
	}

	protected Model getModel() {
		return m_profile.getModel();
	}
	
	protected IStructuredClass objectToStructuredClass(Resource object) {
		IStructuredClass sClass = (IStructuredClass) m_objectToType.get(object);
		if (sClass == null) {
			sClass = m_schemaRegistry.getStructuredClassForObject(object);
			if (sClass != null) {
				m_objectToType.put(object, sClass);
			}
		}
		return sClass;
	}
	
	protected String getObjectLabel(Resource object, Model model, boolean abbreviate) {
		String label = null;
		Model schemaModel = getModel();
		
		/*
		 * Find label based on explicit types on the object
		 */
		IStructuredClass sClass = objectToStructuredClass(object);
		if (sClass != null) {
			String typeURI = sClass.getURI();
			String labelPropertyURI = 
				(String) m_typeLabelPropertyCache.get(typeURI);
			
			check:if (labelPropertyURI == null) {
				StmtIterator si = schemaModel.listStatements(
						null, RDFS.domain, schemaModel.createResource(typeURI));
				
				while (si.hasNext()) {
					Resource property = si.nextStatement().getSubject();
					
					if (isLabelOrTitleSubProperty(schemaModel, property.getURI())) {
						labelPropertyURI = property.getURI();
						
						m_typeLabelPropertyCache.put(typeURI, labelPropertyURI);
						
						break check;
					}
				}
				
				m_typeLabelPropertyCache.put(typeURI, "");
			}
			
			if (labelPropertyURI != null && labelPropertyURI.length() > 0) {
				try {
					label = model.getProperty(
						object, 
						model.createProperty(labelPropertyURI)
					).getString();
				} catch (Exception e) {
				}
			}
		}
		
		/*
		 * Find label based on the property on the object (this is very costly)
		 */
/*		if (label == null) {
			StmtIterator si = model.listStatements(object, null, (RDFNode) null);
			while (si.hasNext()) {
				Statement 	stmt = si.nextStatement();
				Property 	property = stmt.getPredicate();
				
				if (isLabelOrTitleSubProperty(model, property.getURI())) {
					label = stmt.getString();
					
					break;
				}
			}
		}
*/			
		if (label == null) {
			try {
				label = model.getProperty(object, RDFS.label).getString();
			} catch (Exception e) {
			}
		}
		if (label == null) {
			try {
				label = model.getProperty(object, DC.title).getString();
			} catch (Exception e) {
			}
		}
		if (label == null && model != schemaModel) {
			label = getObjectLabel(object, schemaModel, abbreviate);
		}
		if (label == null) {
			if (object.isAnon()) {
				ResourceBundle resources = 
					ResourceBundle.getBundle(LocalSchemaModel.class.getName());
				
				label = resources.getString("AnonymousLabel");
			} else {
				label = resourceToPseudoURI(object);
				if (abbreviate) {
					label = SimileUtilities.abbreviateURI(label);
				}
			}
		}
		
		return label;
	}
	
	static protected boolean isLabelOrTitleSubProperty(Model model, String uri) {
		Property p = model.createProperty(uri);
		
		return 
			model.contains(p, RDFS.subPropertyOf, RDFS.label) || 
			model.contains(p, RDFS.subPropertyOf, DC.title);
	}
	
}

class LabeledObjectComparator implements Comparator {
	/* (non-Javadoc)
	 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
	 */
	public int compare(Object o1, Object o2) {
		return compareLabeledObject(
				(ISchemaModel.LabeledObject) o1,
				(ISchemaModel.LabeledObject) o2);
	}
	
	static int compareLabeledObject(
		ISchemaModel.LabeledObject lo1,
		ISchemaModel.LabeledObject lo2) {
		
		int i = lo1.m_label.compareToIgnoreCase(lo2.m_label);
		if (i == 0) {
			i = lo1.m_object.toString().compareTo(lo2.m_object.toString());
		}
		return i;
	}
}

class PropertyValuePairComparator implements Comparator {

	/* (non-Javadoc)
	 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
	 */
	public int compare(Object o1, Object o2) {
		ISchemaModel.PropertyValuePair p1 = (ISchemaModel.PropertyValuePair) o1;
		ISchemaModel.PropertyValuePair p2 = (ISchemaModel.PropertyValuePair) o2;
		
		return LabeledObjectComparator.compareLabeledObject(
			p1.m_property,
			p2.m_property
		);
	}
}

